import {hiberarchyToTree,setTreeSpan,setTreeTransposeSpan,
    setTreeAttr,getAixsYMatrix,getAixsXMatrix,setTreeLeafCount,setTreeSumNode,
    getSubCubeData,getTreeLeaf} from './treeUtil.js'

const splitChar =',';

export default class xCubeData{
    vCfg;
    vKeyMap = new Map();
    vAxisX;
    vTreeX;
    vAxisY;
    vTreeY;
    vData;
    vAxisYMatrix;
    vAxisXMatrix;
    vDataMatrix;
    vLeafsX;
    vLeafsY;

    vFilterKeys={}
    /*定义变量 结束*/
    // 构造函数
    setLabelAndMap(item,keys,type){
        let tmpArray=[];
        for(let k of keys){
            tmpArray.push(item[k.$code]);
            let mapKey = k.$code+splitChar+item[k.$code];
            let mapVal = k.$name?item[k.$name]:item[k.$code];
            this.vKeyMap.set(mapKey,mapVal);
        }
        item['_label'+type] = tmpArray.join(splitChar);
    };

    setAxis (){
        let xSet = new Set();
        let ySet = new Set();
        for(let d of this.vData){
            this.setLabelAndMap(d,this.vCfg.keysX,'X');
            xSet.add(d._labelX);
            this.setLabelAndMap(d,this.vCfg.keysY,'Y');
            ySet.add(d._labelY);
        };
        this.vAxisX = this.getSortLabel(xSet,this.vCfg.keysX);
        this.vAxisY = this.getSortLabel(ySet,this.vCfg.keysY);
    };

    getSortLabel(set,keys){
        let array = Array.from(set);
        array.sort((a,b) =>{
            let keysOfa = a.split(splitChar);
            let keysOfb = b.split(splitChar);
            let result = 0;
            for(let i in  keys){
                // type keys[i].type
                if (keys[i].DataType && keys[i].DataType.toLowerCase() == 'number')
                    result = keysOfa[i]- keysOfb[i];
                else
                    result =  keysOfa[i]>keysOfb[i]?1:keysOfa[i]==keysOfb[i]?0:-1;
                if (result!=0) break;
            }
            return result;
        });
        return array;
    };

    findIndex(axis,label){
        let result =-1;
        for(let x in axis){
            if(label==axis[x]) {
                result = x;
                break;
            }
        }
        return result;
    }

    prepare(cfg){
        this.vCfg =cfg;
        this.filter();
        this.setAxis();
        this.setDataMatrix();
        this.vTreeY = hiberarchyToTree(this.axisToHiberarchy(this.vAxisY,this.vCfg.keysY));
        this.vTreeX = hiberarchyToTree(this.axisToHiberarchy(this.vAxisX,this.vCfg.keysX));
        setTreeAttr(this.vTreeX);
        setTreeAttr(this.vTreeY);
        setTreeLeafCount(this.vTreeX);
        setTreeLeafCount(this.vTreeY);
        this.setLeafs();
        this.setLeafsIndex();
        /*树要处理2次*/
        setTreeSumNode(this.vTreeY,this.vLeafsY);
        setTreeSumNode(this.vTreeX,this.vLeafsX);
        /*增加了节点 需要重新计算  leafCount he span ;
        * 相比 pivot  data matrix  不需要变化 ， X matirx 和 Y matrix  变化了。
        * */
        setTreeLeafCount(this.vTreeX);
        setTreeLeafCount(this.vTreeY);
        setTreeSpan(this.vTreeX,this.vCfg.keysX.length);
        setTreeTransposeSpan(this.vTreeY,this.vCfg.keysY.length);
        this.setLeafs();
        this.setAixsYMatrix();
        this.setAixsXMatrix();
    }

    axisToHiberarchy(axis,keys){
        let array =[];
        function isNotExist(code){
            let result=true;
            for(let o of array){
                if (o.code==code){
                    result = false;
                    break;
                }
            }
            return result;
        }

        for(let a of axis){
            let subs = a.split(splitChar);
            for(let i=0;i<subs.length;i++){
                let code =  subs.slice(0,i+1).join(splitChar);
                // 两种情况下 需要 push 到数组中
                // 1. 是叶子
                // 2  非叶子  数组中不存在的
                if((code==a?true:isNotExist(code)?true:false)){
                    let obj = {};
                    array.push(obj);
                    obj.code = subs.slice(0,i+1).join(splitChar);
                    obj.pCode = i==0?'':subs.slice(0,i).join(splitChar);
                    obj.name = this.vKeyMap.get(keys[i].$code+splitChar+subs[i]);
                }
            }
        }
        return array;
    }

    setDataMatrix(){
        let matrix =[];
        this.vAxisY.forEach( x => matrix.push([]) );
        for(let d of this.vData){
            let x =  this.findIndex(this.vAxisX,d._labelX);
            let y =  this.findIndex(this.vAxisY,d._labelY);
            if(x==-1 || y==-1)
                break;
            if(!matrix[y][x])
                matrix[y][x] =[];
            matrix[y][x].push(d);
        }
        this.vDataMatrix = matrix;
    }

    setLeafs(){
        this.vLeafsX = getTreeLeaf(this.vTreeX);
        this.vLeafsY = getTreeLeaf(this.vTreeY);
    }

    setLeafsIndex(){
        for(let i=0;i<this.vLeafsX.length;i++){
            this.vLeafsX[i]._X = i;
        }
        for(let i=0;i<this.vLeafsY.length;i++){
            this.vLeafsY[i]._Y = i;
        }
    }

    setAixsYMatrix(){
       this.vAxisYMatrix = getAixsYMatrix(this.vTreeY,this.vLeafsY);
    }

    setAixsXMatrix(){
        this.vAxisXMatrix = getAixsXMatrix(this.vTreeX,this.vCfg.keysX.length);
    }

    // 字段名
    getMapDataByField(field){
        let data =[];
        this.vKeyMap.forEach((value,key) =>{
            if (key.split(splitChar)[0]==field)
                data.push({code:key,name:value})
        })
        this.sortDataByField(field,data);
        return data;
    }

    sortDataByField(field,data){
        let keys =[...this.vCfg.keysX,...this.vCfg.keysY];
        let key;
        for(let k of keys){
            if (k.$code == field){
                key = k;
                break;
            }
        }
        data.sort((a,b) =>{
            let codeA = a.code.split(splitChar)[1] ;
            let codeB = b.code.split(splitChar)[1];
            if (key.DataType && key.DataType.toLowerCase() == 'number')
                return codeA-codeB;
            else
                return codeA>codeB?1:codeA==codeB?0:-1;
        });


    }
    // 这里key参数是字段名
    getSelectByField(field){
        let select =[];
        if(this.vFilterKeys[field])
            this.vFilterKeys[field].forEach(k=> select.push(field+','+k));
        return select;
    }


    addSelect(field,select){
        this.vFilterKeys[field]= [];
        for(let s of select){
            this.vFilterKeys[field].push(s.split(',')[1]);
        }
    }

    getTuple(nodeY,nodeX){
        let Ys;
        let Xs;
        switch((nodeY._type?1:0)+(nodeX._type?4:2)){
           //x y 都为点
            case 2:
                Ys=[nodeY._Y,nodeY._Y];
                Xs=[nodeX._X,nodeX._X];
                break;
           //x 是点 Y 为面
            case 3:
                Ys=[nodeY._from,nodeY._to];
                Xs=[nodeX._X,nodeX._X];
                break;
           // X 是面 Y 为点
            case 4:
                Ys=[nodeY._Y,nodeY._Y];
                Xs=[nodeX._from,nodeX._to];
                break;
           // X,Y 都为面
            case 5:
                Ys=[nodeY._from,nodeY._to];
                Xs=[nodeX._from,nodeX._to];
                break;
       }
        return getSubCubeData(this.vDataMatrix,Ys,Xs);
    }

    isActiveFilter(field){
        return this.vFilterKeys[field]?true:false;
    }

    clearAllFilter(){
        this.vFilterKeys={};
    }

    //过滤数据
    filter(){
        if(Object.keys(this.vFilterKeys).length>0){
            this.vData = [];
            for(let d of this.vCfg.data){
                let ok =true;
                for(let field in this.vFilterKeys){
                    let inSelect = this.vFilterKeys[field].includes(d[field]+'');
                    if(!inSelect){
                        ok = false;
                        break;
                    }
                }
                if(ok)
                    this.vData.push(d);
            }
        }else
            this.vData = this.vCfg.data ;
    }

}